#include "SDL.h"
#include <GL/glew.h>
#include <AntTweakBar.h>

namespace {

const int kWindowWidth = 800;
const int kWindowHeight = 600;

class Eneida {
 public:
  Eneida();
  ~Eneida();
  int Run();

 private:
  void Init();
  void Update();

  GLuint path_;
};

Eneida::Eneida() {
}

Eneida::~Eneida() {
  TwTerminate();
  SDL_Quit();
}

void Eneida::Update() {
  glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

  glColor3f(1.0f, 0.0f, 0.0f);
  glRectf(-0.5f, -0.5f, 0.5f, 0.5f);

  // stencil the path
  glStencilFillPathNV(path_, GL_COUNT_UP_NV, 0x1f);

  // cover the path
  glColor3f(0.0f, 1.0f, 0.0f);
  glEnable(GL_STENCIL_TEST);
  glStencilFunc(GL_NOTEQUAL, 0, 0x1f);
  glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
  glCoverFillPathNV(path_, GL_BOUNDING_BOX_NV);
  glDisable(GL_STENCIL_TEST);

  // draw GUI
  glUseProgram(0);
  glBindVertexArray(0);
  TwDraw();
}

void Eneida::Init() {
  SDL_Init(SDL_INIT_VIDEO);
  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
  SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
  SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
  SDL_SetVideoMode(kWindowWidth, kWindowHeight, 0, SDL_OPENGL | SDL_NOFRAME);

  glewInit();

  // create path object
  const GLubyte cmds[] = {
    GL_MOVE_TO_NV, GL_LINE_TO_NV, GL_LINE_TO_NV, GL_LINE_TO_NV, GL_LINE_TO_NV,
    GL_LINE_TO_NV, GL_LINE_TO_NV, GL_CLOSE_PATH_NV
  };
  const GLfloat coords[] = {
    -0.5,-0.5, 0.5,-0.5, 0.5,0.5, 0.3,0.5, 0.3,-0.3, -0.3,-0.3, -0.3,0.3
  };
  path_ = glGenPathsNV(1);
  glPathCommandsNV(path_, sizeof(cmds), cmds, sizeof(coords)/4, GL_FLOAT,
                   coords);
  // GUI
  TwInit(TW_OPENGL, NULL);
  TwWindowSize(kWindowWidth, kWindowHeight);

  TwBar *bar = TwNewBar("Menu");
  TwDefine("Menu color='0 0 0' alpha=128 position='10 10' size='240 90'");
  TwDefine("Menu fontresizable=false resizable=false");
}

int Eneida::Run() {
  Init();

  while (true) {
    SDL_Event evt;
    while (SDL_PollEvent(&evt)) {
      if (TwEventSDL(&evt, 1, 2)) continue;

      switch (evt.type) {
        case SDL_QUIT:
          return 0;
        case SDL_KEYDOWN:
          if (evt.key.keysym.sym == SDLK_ESCAPE) {
            return 0;
          }
          break;
      }
    }

    Update();
    SDL_GL_SwapBuffers();
  }
  return 0;
}

} // namespace

int main(int argc, char *argv[]) {
  Eneida en;
  return en.Run();
}
